#ifndef WORKER_H_
#define WORKER_H_

#include <string>
#include <unordered_map>
#include <set>
#include <list>
#include <uv.h>

#include "session.h"

typedef struct
{
    uint32_t mask;
    std::set<uint32_t> IPTbl;
} MaskIpSet;

enum {
    WORKER_TYPE_PROXY  = 0,
    WORKER_TYPE_SPIDER =1
};


class Worker
{
private:
    int m_index;
    int m_workerType;
    int m_listenPortStart;
    int m_listenPortEnd;
    int m_listenNum;
    int m_spiderPort;
    int m_commandTimeout;
    int m_idleTimeout;

    std::unordered_map<std::string, std::string> m_identification;
    std::list<MaskIpSet> m_whiteList;

    uint32_t m_sessionId; 

    uv_thread_t m_workerTid;
    uv_loop_t *m_workerLoop;
    uv_tcp_t *m_sessionServer;
    uv_tcp_t m_spiderServer;
    std::unordered_map<uint32_t, Session *> m_sessionCache;

public:
    Worker() = default;
    ~Worker() = default;

    uv_loop_t *GetLoop() {
        return m_workerLoop;
    };
    int GetIndex() const {
        return m_index;
    };
    int GetType() const {
        return m_workerType;
    };
    uint16_t GetSpiderPort() const {
        return m_spiderPort;
    };

    bool Init(int index, int workerType, int listenPortStart, int listenPortEnd, int spiderPort, int commandTimeout, int idleTimeout);
    bool AddIdentification(const std::string username, const std::string password);
    bool AddWhiteList(const std::string ipMask);
    bool DoAuth(const std::string username, const std::string password, uint32_t ipaddr);
    bool Start();
    void Stop();

    void RunLoop();
    void OnRecvSessionConnection(uv_stream_t* pServer);
    void OnRecvSpiderConnection(uv_stream_t* pServer);

    bool AddSessionCache(Session *pNode);
    void DelSessionCache(Session *pNode);

    Session *FindSessionCache(uint32_t SessionId);
    
    void ShowWorker() const;
};

class SpiderBackConn {
public:
    SpiderBackConn() = default;
    ~SpiderBackConn() = default;
    Worker *m_pWorker;
    char m_cmdRecvBuf[4];
    uv_tcp_t *m_targetTcp;
    uv_timer_t m_sessionTimer;

    void DoConn();
    void Close();
} ;

#endif